home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Contributions / Interworks / Networking / INet-225 / examples / timed / timed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-08  |  5.2 KB  |  275 lines

  1. /*
  2. **  timed.c
  3. */
  4.  
  5. #include <proto/dos.h>
  6. #include <proto/exec.h>
  7. #include <proto/socket.h>
  8.  
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <sys/syslog.h>
  12. #include "timed_rev.h"
  13.  
  14. static const char ver[] = VERSTAG;
  15.  
  16. #pragma msg 105 ignore
  17.  
  18. #define TEMPLATE "NAME/A,SOCKPTR/A/N,ID/A/N,ARGS/F"
  19.  
  20. struct Args {
  21.     char *name;
  22.     long *sockptr;
  23.     long *id;
  24.     char *args;
  25. };
  26.  
  27. struct global {
  28.     struct ExecBase *e;
  29.     struct DosLibrary *d;
  30.     struct Library *s;
  31.     int errno;
  32. };
  33.  
  34. #define SysBase  g->e
  35. #define DOSBase  g->d
  36. #define SockBase g->s
  37.  
  38. static void machtime_dg (struct global *g, int);
  39. static void daytime_dg (struct global *g, int);
  40. static void machtime_stream (struct global *g, int);
  41. static void daytime_stream (struct global *g, int);
  42. static void SPrintf (struct global *g, char *buf, char *ctl, ...);
  43. static int  openlibs (struct global *g);
  44. static void closelibs (struct global *g);
  45. static int  reply_inet (struct global *g, long id);
  46.  
  47. struct inetmsg {
  48.     struct Message msg;
  49.     ULONG id;
  50. };
  51.  
  52. long
  53. timed (void)
  54. {
  55.     int s;
  56.     long result = RETURN_FAIL;
  57.     struct RDArgs *rdargs;
  58.     struct global glob, *g = &glob;
  59.     struct Args arg;
  60.  
  61.     SysBase = *((struct ExecBase **) 4L);
  62.  
  63.     if (openlibs (g))
  64.     {
  65.         memset ((char *) &arg, 0, sizeof (struct Args));
  66.         if (rdargs = ReadArgs (TEMPLATE, (LONG *) &arg, NULL))
  67.         {
  68.             setup_sockets (5, &g->errno);
  69.  
  70.             /* now get our socket, if we can */
  71.             if (*arg.sockptr && ((s = s_inherit ((void *) *arg.sockptr)) >= 0))
  72.             {
  73.                 result = stricmp (arg.name, "time");
  74.  
  75.                 if (arg.args && *arg.args == 'U')
  76.                 {
  77.                     /* UDP */
  78.                     if (result)
  79.                         daytime_dg (g, s);      /* service name of daytime */
  80.                     else
  81.                         machtime_dg (g, s);     /* service name of time */
  82.                 }
  83.                 else
  84.                 {
  85.                     /* TCP */
  86.                     if (result)
  87.                         daytime_stream (g, s);  /* service name of daytime */
  88.                     else
  89.                         machtime_stream (g, s); /* service name of time */
  90.                 }
  91.  
  92.                 result = RETURN_OK;
  93.                 s_close (s);
  94.             }
  95.  
  96.             /* if id was nonzero, then we have to inform inetd that we are done */
  97.             if (*arg.id)
  98.             {
  99.                 result = reply_inet (g, *arg.id);
  100.             }
  101.  
  102.             cleanup_sockets ();
  103.  
  104.             FreeArgs (rdargs);
  105.         }
  106.         closelibs (g);
  107.     }
  108.  
  109.     return result;
  110. }
  111.  
  112. static void
  113. daytime (struct global *g, char *str)
  114. {
  115.     struct DateTime dt;
  116.     char day [20], date [20], time [20];
  117.  
  118.     dt.dat_Format  = FORMAT_DOS;
  119.     dt.dat_Flags   = 0;
  120.     dt.dat_StrDay  = day;
  121.     dt.dat_StrTime = time;
  122.     dt.dat_StrDate = date;
  123.     DateStamp (&dt.dat_Stamp);
  124.     DateToStr (&dt);
  125.     SPrintf (g, str, "%s %s %s\r\n", day, date, time);
  126. }
  127.  
  128.  
  129. /* Return human-readable time of day */
  130. static void
  131. daytime_stream (struct global *g, int s)
  132. {
  133.     char buffer [128];
  134.  
  135.     daytime (g, buffer);
  136.     send (s, buffer, strlen (buffer), 0);
  137. }
  138.  
  139. static void
  140. daytime_dg (struct global *g, int s)
  141. {
  142.     char buffer [128];
  143.     struct sockaddr sa;
  144.     int size;
  145.  
  146.     size = sizeof (sa);
  147.     if (recvfrom (s, buffer, sizeof (buffer), 0, &sa, &size) < 0)
  148.         return;
  149.     daytime (g, buffer);
  150.     sendto (s, buffer, strlen (buffer), 0, &sa, sizeof (sa));
  151. }
  152.  
  153.  
  154. /*
  155.  * Return a machine readable date and time, in the form of the
  156.  * number of seconds since midnight, Jan 1, 1900.  Since DateStamp
  157.  * returns the number of seconds since midnight, Jan 1, 1978,
  158.  * we must add 246144960 seconds.
  159.  */
  160.  
  161.  
  162. static long
  163. machtime (struct global *g)
  164. {
  165.     struct DateStamp ds;
  166.     long t;
  167.  
  168.     DateStamp (&ds);
  169.     t = (ds.ds_Days * 86400) + (ds.ds_Minute * 60) + ((long)(ds.ds_Tick / 50));
  170.     t += 2461449600;
  171.  
  172.     return t;
  173. }
  174.  
  175.  
  176. static void
  177. machtime_stream (struct global *g, int s)
  178. {
  179.     long result;
  180.  
  181.     result = machtime (g);
  182.     send (s, (char *) &result, sizeof (result), 0);
  183. }
  184.  
  185. static void
  186. machtime_dg (struct global *g, int s)
  187. {
  188.     long result;
  189.     struct sockaddr sa;
  190.     int size;
  191.  
  192.     size = sizeof (sa);
  193.     if (recvfrom (s, (char *) &result, sizeof (result), 0, &sa, &size) < 0)
  194.         return;
  195.  
  196.     result = machtime (g);
  197.     sendto (s, (char *) &result, sizeof (result), 0, &sa, sizeof (sa));
  198. }
  199.  
  200. static void SPrintf (struct global *g, char *buf, char *ctl, ...)
  201. {
  202.     RawDoFmt (ctl, (long *)(&ctl + 1), (void (*))"\x16\xC0\x4E\x75", buf);
  203. }
  204.  
  205. static int
  206. openlibs (struct global *g)
  207. {
  208.     if (g->d = (struct DosLibrary *) OpenLibrary ("dos.library", 0))
  209.     {
  210.         if (g->s = OpenLibrary ("inet:libs/socket.library", 0))
  211.         {
  212.             return 1;
  213.         }
  214.         CloseLibrary ((struct Library *) g->d);
  215.         g->d = NULL;
  216.     }
  217.     return 0;
  218. }
  219.  
  220. static void closelibs (struct global *g)
  221. {
  222.     /* don't call me if these libraries didn't get opened! */
  223.  
  224.     CloseLibrary ((struct Library *) g->d);
  225.     CloseLibrary (g->s);
  226.  
  227.     g->d = NULL;
  228.     g->s = NULL;
  229.  
  230.     return;
  231. }
  232.  
  233. static int
  234. reply_inet (struct global *g, long id)
  235. {
  236.     int
  237.         result = RETURN_OK;
  238.     struct MsgPort
  239.         *replyport,
  240.         *msgport;
  241.     struct inetmsg
  242.         inet_message;
  243.  
  244.     if (replyport = CreateMsgPort ())
  245.     {
  246.         inet_message.id = id;
  247.         inet_message.msg.mn_Node.ln_Type = NT_MESSAGE;
  248.         inet_message.msg.mn_Length = sizeof (struct inetmsg);
  249.         inet_message.msg.mn_ReplyPort = replyport;
  250.  
  251.         Forbid ();
  252.         if (msgport = FindPort ("inetd"))
  253.         {
  254.             PutMsg (msgport, (struct Message *) &inet_message);
  255.             Permit ();
  256.             /* we can't exit until we received a reply */
  257.             WaitPort (replyport);
  258.         }
  259.         else
  260.         {
  261.             Permit ();
  262.             s_syslog (LOG_ERR, "TIMED: Couldn't find inetd port\n");
  263.             result = RETURN_FAIL;
  264.         }
  265.         DeleteMsgPort (replyport);
  266.     }
  267.     else
  268.     {
  269.         s_syslog (LOG_ERR, "TIMED: Couldn't create reply port\n");
  270.         result = RETURN_FAIL;
  271.     }
  272.  
  273.     return result;
  274. }
  275.